package com.bot.devbot.job;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.bot.devbot.service.deploy.FrameWorkDeployUtil;
import com.bot.devbot.service.feishu.FeiShuService;
import com.bot.devbot.service.gitlab.GitLabService;
import com.bot.devbot.service.wechat.WeChatService;
import com.bot.devbot.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * Gitlab变更通知定时任务
 *
 * @author xialiguo
 * @version 1.0
 * @date 2025/1/21 15:42
 * @since 1.0
 */
@Slf4j
@Component
public class GitlabNoticeJob {
    private static String NOTICED_COMMIT_ID_FILE_PATH;
    @Autowired
    private GitLabService gitLabService;
    @Autowired
    private WeChatService weChatService;
    @Autowired
    private FeiShuService feiShuService;
    @Value("${myapp.sendWechat:false}")
    private boolean sendWechat;
    @Value("${myapp.sendFeiShu:false}")
    private boolean sendFeiShu;

    private List<String> noticedCommitId;

    // gitlab提交作者信息与企微ID的映射
    private static Map<String, String> AUTHOR_GITLAB_REALNAME_MAPPING = new HashMap<>();

    public static Map<String, String> getAuthorWechatUserMapping() {
        if (CollUtil.isEmpty(AUTHOR_GITLAB_REALNAME_MAPPING)) {
            synchronized (WeChatService.class) {
                if (AUTHOR_GITLAB_REALNAME_MAPPING == null) {
                    AUTHOR_GITLAB_REALNAME_MAPPING = new HashMap<>();
                }
                AUTHOR_GITLAB_REALNAME_MAPPING.put("毛福江", "毛福江");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("maofujiang", "毛福江");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("zhuwenxu", "朱文旭");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("朱文旭", "朱文旭");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("黄宇辰", "黄宇辰");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("huangyuchen", "黄宇辰");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("刘鸿", "刘鸿");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("liuhong", "刘鸿");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("罗云鹏", "罗云鹏");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("“luoyunpeng”", "罗云鹏");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("李佳文", "李佳文");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("lijiawen", "李佳文");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("Li jia wen", "李佳文");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("蔡世金", "蔡世金");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("caishijin", "蔡世金");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("夏利国", "夏利国");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("xialiguo", "夏利国");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("范奇伟", "范奇伟");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("fanqiwei", "范奇伟");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("fanic", "范奇伟");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("蒋义琪", "蒋义琪");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("jiangyiqi", "蒋义琪");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("Plt-蒋义琪", "蒋义琪");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("zhangyongping", "张永平");
                AUTHOR_GITLAB_REALNAME_MAPPING.put("张永平", "张永平");
            }
        }
        return AUTHOR_GITLAB_REALNAME_MAPPING;
    }

    @PostConstruct
    public void init() {
        log.info("项目初始化,创建或加载DevBotApplication-data/noticedCommitId.log");
        // 动态设置NOTICED_COMMIT_ID_FILE_PATH
        try {
            URL jarUrl = getClass().getProtectionDomain().getCodeSource().getLocation();
            String jarFilePath = null;

            if ("jar".equalsIgnoreCase(jarUrl.getProtocol())) {
                // 处理嵌套的 JAR URI
                String path = jarUrl.getPath();
                if (path != null && path.startsWith("file:")) {
                    path = path.substring(5); // 去掉 "file:"
                    int separatorIndex = path.indexOf("!/");
                    if (separatorIndex > 0) {
                        path = path.substring(0, separatorIndex);
                    }
                    jarFilePath = URLDecoder.decode(path, StandardCharsets.UTF_8.name());
                }
            } else if ("file".equalsIgnoreCase(jarUrl.getProtocol())) {
                // 直接是文件路径
                jarFilePath = URLDecoder.decode(jarUrl.getFile(), StandardCharsets.UTF_8.name());
            }

            if (jarFilePath == null) {
                throw new RuntimeException("无法解析JAR包路径");
            }

            File jarFile = new File(jarFilePath);
            String jarDirPath = jarFile.getParentFile().getAbsolutePath();
            NOTICED_COMMIT_ID_FILE_PATH = new File(jarDirPath, "DevBotApplication-data/noticedCommitId.log").getAbsolutePath();
            log.info("NOTICED_COMMIT_ID_FILE_PATH: {}", NOTICED_COMMIT_ID_FILE_PATH);
            File dataDir = new File(jarDirPath, "DevBotApplication-data");
            if (!dataDir.exists()) {
                dataDir.mkdir(); // 创建data目录
            }
        } catch (Exception e) {
            throw new RuntimeException("无法确定JAR包所在目录: " + e.getMessage(), e);
        }

        log.info("从磁盘加载DevBotApplication-data/noticedCommitId.log");
        this.noticedCommitId = loadNoticedCommitIdFromDisk();
        log.info("noticedCommitId size: {}", noticedCommitId.size());

        if (CollUtil.isEmpty(this.noticedCommitId)) {
            log.info("DevBotApplication-data/noticedCommitId.log不存在,初始化noticedCommitId");
            initCommitId();
        }
        log.info("noticedCommitId初始化完成");
    }

    private void initCommitId() {
        JSONArray projects = gitLabService.getAllProjectsV1();
        for (Object projectObj : projects) {
            JSONObject project = (JSONObject) projectObj;
            String projectId = project.getStr("id");
            // 获取项目所有分支信息
            JSONArray branches = gitLabService.getBranchesV2(projectId);
            for (Object branchObj : branches) {
                JSONObject branch = (JSONObject) branchObj;
                String branchName = branch.getStr("name");
                // 获取该分支最新的提交记录commits
                JSONArray commits = gitLabService.getAllCommits(projectId, branchName);
                if (commits.isEmpty()) continue;
                // 倒序遍历
                for (int i = commits.size() - 1; i >= 0; i--) {
                    JSONObject latestCommit = commits.getJSONObject(i);
                    String latestCommitId = latestCommit.getStr("id");
                    if (noticedCommitId.contains(latestCommitId)) {
                        // 其他分支已经推送过该commitId，跳过
                        continue;
                    }
                    noticedCommitId.add(latestCommitId);
                    appendNoticedCommitIdToDisk(latestCommitId);
                }

            }
        }
    }

    @Scheduled(cron = "0 0/1 * * * ?")
    public synchronized void fetchAndSendCommits() {
        log.info("定时任务: 开始检测gitlab最新提交记录");
        JSONArray projects = gitLabService.getAllProjectsV1();
        int noticeCountWechat = 0;
        int noticeCountFeishu = 0;
        for (Object projectObj : projects) {
            JSONObject project = (JSONObject) projectObj;
            String projectId = project.getStr("id");
            String projectName = project.getStr("name");
            // 获取项目所有分支信息
            JSONArray branches = gitLabService.getBranchesV2(projectId);
            for (Object branchObj : branches) {
                JSONObject branch = (JSONObject) branchObj;
                String branchName = branch.getStr("name");

                // 获取该分支最新的提交记录commits
                JSONArray commits = gitLabService.getCommitsV2(projectId, branchName);
                if (commits.isEmpty()) {
                    continue;
                }
                // 倒序遍历
                for (int i = commits.size() - 1; i >= 0; i--) {
                    JSONObject latestCommit = commits.getJSONObject(i); // 最新提交
                    String latestCommitId = latestCommit.getStr("id");
                    // 发送消息到企业微信
                    if (noticedCommitId.contains(latestCommitId)) {
                        // 其他分支已经推送过该commitId，跳过
                        continue;
                    }
                    // deploy至maven私服
                    FrameWorkDeployUtil.deployFilter(projectName, branchName);

                    String author = latestCommit.getStr("author_name");

                    String wechatMsg = buildWechatMsg(projectName, branchName, author, latestCommit);
                    if (sendWechat) {
                        if (noticeCountWechat <= 5) {
                            // log.info("模拟企微发送:{}", latestCommitId);
                            weChatService.sendMessageMdV2FromCnf(projectName, branchName, author, wechatMsg);
                        } else {
                            log.warn("企微发送超过限制,不发");
                        }
                        noticeCountWechat++;

                    }

                    String feiShuMsg = buildFeiShuMsg(projectName, branchName, latestCommit);
                    if (sendFeiShu) {
                        if (noticeCountFeishu <= 5) {
                            // log.info("模拟飞书发送:{}", latestCommitId);
                            feiShuService.sendMessagePost(projectName, branchName, feiShuMsg, latestCommit.getStr("web_url"));
                        } else {
                            log.warn("飞书发送超过限制,不发");
                        }
                    }
                    noticedCommitId.add(latestCommitId);
                    appendNoticedCommitIdToDisk(latestCommitId);
                    log.info(wechatMsg);
                }

            }
        }
    }

    private String buildWechatMsg(String projectName, String branchName, String author,JSONObject latestCommit) {
        Map<String, String> authorWechatUserMapping = getAuthorWechatUserMapping();
        String realName = MapUtil.getStr(authorWechatUserMapping, author, author);
        return String.format("项目:%s\n分支:%s\n最新变更如下：\n" +
                        ">@msg:%s" +
                        "\n@author:%s" +
                        "\n@date:%s" +
                        "\n[变更内容](%s?view=parallel)",
                projectName, branchName, latestCommit.getStr("message").replace("\n", ""),
                realName, DateUtil.timeFromGitlabToLocal(latestCommit.getStr("committed_date")), latestCommit.getStr("web_url"));
    }

    private String buildFeiShuMsg(String projectName, String branchName, JSONObject latestCommit) {
        StringBuilder message = new StringBuilder();
        String author = latestCommit.getStr("author_name");
        Map<String, String> authorWechatUserMapping = getAuthorWechatUserMapping();
        String realName = MapUtil.getStr(authorWechatUserMapping, author, author);
        message.append("项目: ").append(projectName)
                .append("\n分支: ").append(branchName)
                .append("\n最新变更如下：\n")
                .append("- 提交信息: ").append(latestCommit.getStr("message").replace("\n", ""))
                .append("\n- 作者: ").append(realName)
                .append("\n- 提交时间: ").append(DateUtil.timeFromGitlabToLocal(latestCommit.getStr("committed_date")));
        return message.toString();
    }

    /**
     * 将 noticedCommitId 追加到磁盘
     */
    private void appendNoticedCommitIdToDisk(String commitId) {
        try {
            File file = new File(NOTICED_COMMIT_ID_FILE_PATH);
            // 使用追加模式写入新commitId
            FileUtil.appendUtf8String(commitId + "\n", file);
        } catch (Exception e) {
            throw new RuntimeException("追加 noticedCommitId 到文件失败: " + e.getMessage(), e);
        }
    }

    /**
     * 从磁盘加载 noticedCommitId 列表，并去除重复项
     *
     * @return 去重后的 noticedCommitId 列表
     */
    private List<String> loadNoticedCommitIdFromDisk() {
        File file = new File(NOTICED_COMMIT_ID_FILE_PATH);
        if (file.exists()) {
            try {
                List<String> lines = FileUtil.readUtf8Lines(file);
                return new ArrayList<>(new LinkedHashSet<>(lines)); // 使用LinkedHashSet去重同时保持插入顺序
            } catch (Exception e) {
                throw new RuntimeException("加载 noticedCommitId 失败: " + e.getMessage(), e);
            }
        }
        return new ArrayList<>();
    }

    public static void main(String[] args) {
        // 输入的时间字符串
        String time1 = "2025-02-19T02:58:05.000+00:00";
        String time2 = "2025-02-19T11:24:23.000+08:00";
        String time3 = "2025-02-18T09:42:18.194+00:00";
        System.out.println("转换后的时间1: " + DateUtil.timeFromGitlabToLocal(time1));
        System.out.println("转换后的时间2: " + DateUtil.timeFromGitlabToLocal(time2));
        System.out.println("转换后的时间3: " + DateUtil.timeFromGitlabToLocal(time3));
    }
}
